package com.mapfinal.server.geoserver;

import java.io.File;
import java.util.List;
import java.util.Map;

import org.apache.commons.httpclient.NameValuePair;

import com.google.common.collect.Maps;
import com.jfinal.kit.StrKit;
import com.jfinal.render.Render;
import com.lambkit.core.gateway.GatewayRender;
import com.mapfinal.data.MapLayer;
import com.mapfinal.server.Server;
import com.mapfinal.server.ServerLayer;
import com.mapfinal.server.geoserver.rest.GeoServerRESTPublisher;
import com.mapfinal.server.geoserver.rest.GeoServerRESTReader;
import com.mapfinal.server.geoserver.rest.GeoServerRESTPublisher.UploadMethod;
import com.mapfinal.server.geoserver.rest.decoder.RESTCoverageStoreList;
import com.mapfinal.server.geoserver.rest.decoder.RESTDataStore;
import com.mapfinal.server.geoserver.rest.decoder.RESTDataStoreList;
import com.mapfinal.server.geoserver.rest.decoder.RESTLayer;
import com.mapfinal.server.geoserver.rest.decoder.RESTLayerList;
import com.mapfinal.server.geoserver.rest.decoder.about.GSVersionDecoder;
import com.mapfinal.server.geoserver.rest.encoder.GSLayerEncoder;
import com.mapfinal.server.geoserver.rest.encoder.GSResourceEncoder;
import com.mapfinal.server.geoserver.rest.encoder.GSResourceEncoder.ProjectionPolicy;
import com.mapfinal.server.geoserver.rest.encoder.feature.GSFeatureTypeEncoder;

public class GeoserverServer implements Server {

	private String name;
	private GeoserverConfig config;
	private int rate = 0;
	private boolean exist = false;
	private Map<String, ServerLayer> serverLayers;
	private boolean cluster;

	public GeoserverServer() {
		this.setCluster(false);
	}
	
	/*
	public void init() {
		exist = GeoserverManager.me().getService().existGeoserver(config);
		if(exist) {
			List<String> wks = GeoserverManager.me().getService().getWorkspaceNames(config);
			List<String> layers = GeoserverManager.me().getService().getLayerNames(config);
			for (String wk : wks) {
				GsWorkspace gwk = new GsWorkspace(this);
				gwk.init(layers);
				workspaces.put(wk, gwk);
			}
		}
	}
	*/
	
	public static GeoserverServer create(GeoserverConfig config) {
		if (config == null)
			return null;
		GeoserverServer server = new GeoserverServer();
		server.setName(config.getName());
		server.setConfig(config);
		server.setExist(server.exist());
		return server;
	}

	/////////////////////////////////////////

	public Render wms(String targetName) {
		String targetUri = config.getUrl() + "/" + config.getWorkspace() + "/wms";
		return GatewayRender.by(targetName, targetUri);
	}

	public Render wms(String targetName, String workspace) {
		String targetUri = config.getUrl() + "/" + workspace + "/wms";
		return GatewayRender.by(targetName, targetUri);
	}

	public Render wfs(String targetName) {
		String targetUri = config.getUrl() + "/" + config.getWorkspace() + "/wfs";
		return GatewayRender.by(targetName, targetUri);
	}

	public Render wfs(String targetName, String workspace) {
		String targetUri = config.getUrl() + "/" + workspace + "/wfs";
		return GatewayRender.by(targetName, targetUri);
	}

	/**
	 * 发布PostGIS图层
	 * 
	 * @param layerName
	 * @param tbname
	 * @param epsgCode
	 * @param defaultStyle
	 * @return
	 */
	public boolean publishPg(String layerName, String tbname, String epsgCode, String defaultStyle) {
		if (config == null)
			return false;
		String RESTURL = config.getUrl();// "http://localhost:8080/geoserver";
		String RESTUSER = config.getUser();// "admin";
		String RESTPW = config.getPassword();// "Q7P0XFU$2YRQaq08";
		String workspace = config.getWorkspace();// "map";
		String storename = config.getStorename();// "pg";
		GeoServerRESTPublisher publisher = new GeoServerRESTPublisher(RESTURL, RESTUSER, RESTPW);
		GSFeatureTypeEncoder fte = new GSFeatureTypeEncoder();
		fte.setProjectionPolicy(GSResourceEncoder.ProjectionPolicy.REPROJECT_TO_DECLARED);
		fte.addKeyword("KEYWORD");
		fte.setTitle(layerName);
		fte.setName(tbname);
		fte.setSRS(epsgCode);
		GSLayerEncoder layerEncoder = new GSLayerEncoder();
		layerEncoder.setDefaultStyle(defaultStyle);
		return publisher.publishDBLayer(workspace, storename, fte, layerEncoder);
	}

	/**
	 * 发布shp图层
	 * 
	 * @param layerName
	 * @param resPath
	 * @param epsgCode
	 * @param uploadMethod
	 * @return
	 */
	public boolean publishShp(String layerName, String resPath, String epsgCode, String uploadMethod) {
		if (config == null)
			return false;
		String RESTURL = config.getUrl();// "http://localhost:8080/geoserver";
		String RESTUSER = config.getUser();// "admin";
		String RESTPW = config.getPassword();// "Q7P0XFU$2YRQaq08";
		String workspace = config.getWorkspace();// "jsus";
		String storename = config.getStorename();// "jsus";
		// String resPath = "D:";
		// String uploadMethod = "external";
		// String layername = "mishan";
		// String epsgCode = "EPSG:91901" + 1;

		boolean flag = false;
		List<String> workspaces = null;
		try {
			GeoServerRESTReader reader = new GeoServerRESTReader(RESTURL, RESTUSER, RESTPW);
			GeoServerRESTPublisher publisher = new GeoServerRESTPublisher(RESTURL, RESTUSER, RESTPW);
			workspaces = reader.getWorkspaceNames();
			System.out.println(workspaces);
			if (workspaces.contains(workspace)) {
				UploadMethod method = UploadMethod.EXTERNAL;
				File shpFile = null;
				if (uploadMethod.equals("url")) {
					method = UploadMethod.URL;
					String url = config.getLocurl();// "\\\\127.0.0.1:8080\\";
					shpFile = new File(url + resPath);
				} else if (uploadMethod.equals("file")) {
					// zipfile
					method = UploadMethod.FILE;
					shpFile = new File(resPath);
				} else {
					shpFile = new File(resPath);
				}
				System.out.println("shpFile :" + shpFile);
				flag = publisher.publishShp(workspace, storename, (NameValuePair[]) null, layerName, method,
						shpFile.toURI(), "EPSG:4326", epsgCode, ProjectionPolicy.REPROJECT_TO_DECLARED, null);
			}
		} catch (Exception mue) {
			mue.printStackTrace();
		}
		return flag;
	}

	/**
	 * 服务器是否存在
	 * 
	 * @return
	 */
	public boolean exist() {
		boolean flag = false;
		if (config == null)
			return flag;
		String RESTURL = config.getUrl();// "http://localhost:8080/geoserver";
		String RESTUSER = config.getUser();// "admin";
		String RESTPW = config.getPassword();// "Q7P0XFU$2YRQaq08";
		try {
			GeoServerRESTReader reader = new GeoServerRESTReader(RESTURL, RESTUSER, RESTPW);
			flag = reader.existGeoserver();
		} catch (Exception mue) {
			mue.printStackTrace();
		}
		return flag;
	}

	/**
	 * 获取服务器所有工作空间名单
	 * 
	 * @return
	 */
	public List<String> getWorkspaceNames() {
		List<String> workspaces = null;
		if (config == null)
			return workspaces;
		String RESTURL = config.getUrl();// "http://localhost:8080/geoserver";
		String RESTUSER = config.getUser();// "admin";
		String RESTPW = config.getPassword();// "Q7P0XFU$2YRQaq08";
		try {
			GeoServerRESTReader reader = new GeoServerRESTReader(RESTURL, RESTUSER, RESTPW);
			workspaces = reader.getWorkspaceNames();
		} catch (Exception mue) {
			mue.printStackTrace();
		}
		return workspaces;
	}

	/**
	 * 获取服务器所有矢量存储空间名单
	 * 
	 * @param workspace
	 * @return
	 */
	public List<String> getDataStoreNames(String workspace) {
		RESTDataStoreList store = null;
		if (config == null)
			return null;
		String RESTURL = config.getUrl();
		String RESTUSER = config.getUser();
		String RESTPW = config.getPassword();
		if (StrKit.isBlank(workspace))
			workspace = config.getWorkspace();
		try {
			GeoServerRESTReader reader = new GeoServerRESTReader(RESTURL, RESTUSER, RESTPW);
			store = reader.getDatastores(workspace);
		} catch (Exception mue) {
			mue.printStackTrace();
		}
		return store.getNames();
	}

	/**
	 * 获取服务器矢量存储信息
	 * 
	 * @param workspace
	 * @param dsName
	 * @return
	 */
	public RESTDataStore getDataStore(String workspace, String dsName) {
		RESTDataStore res = null;
		if (config == null)
			return null;
		String RESTURL = config.getUrl();
		String RESTUSER = config.getUser();
		String RESTPW = config.getPassword();
		try {
			GeoServerRESTReader reader = new GeoServerRESTReader(RESTURL, RESTUSER, RESTPW);
			res = reader.getDatastore(workspace, dsName);
		} catch (Exception mue) {
			mue.printStackTrace();
		}
		return res;
	}

	/**
	 * 获取服务器所有影像存储空间名单
	 * 
	 * @param workspace
	 * @return
	 */
	public List<String> getCoverageStoresNames(String workspace) {
		RESTCoverageStoreList store = null;
		if (config == null)
			return null;
		String RESTURL = config.getUrl();
		String RESTUSER = config.getUser();
		String RESTPW = config.getPassword();
		if (StrKit.isBlank(workspace))
			workspace = config.getWorkspace();
		try {
			GeoServerRESTReader reader = new GeoServerRESTReader(RESTURL, RESTUSER, RESTPW);
			store = reader.getCoverageStores(workspace);
		} catch (Exception mue) {
			mue.printStackTrace();
		}
		return store.getNames();
	}

	/**
	 * 获取服务器所有图层列表名单
	 * 
	 * @return
	 */
	public List<String> getLayerNames() {
		RESTLayerList layers = null;
		if (config == null)
			return null;
		String RESTURL = config.getUrl();
		String RESTUSER = config.getUser();
		String RESTPW = config.getPassword();
		try {
			GeoServerRESTReader reader = new GeoServerRESTReader(RESTURL, RESTUSER, RESTPW);
			layers = reader.getLayers();
		} catch (Exception mue) {
			mue.printStackTrace();
		}
		return layers.getNames();
	}

	/**
	 * 获取图层信息
	 * 
	 * @param workspace
	 * @param layer
	 * @return
	 */
	public RESTLayer getLayer(String workspace, String layer) {
		RESTLayer layers = null;
		if (config == null)
			return null;
		String RESTURL = config.getUrl();
		String RESTUSER = config.getUser();
		String RESTPW = config.getPassword();
		try {
			GeoServerRESTReader reader = new GeoServerRESTReader(RESTURL, RESTUSER, RESTPW);
			layers = reader.getLayer(workspace, layer);
		} catch (Exception mue) {
			mue.printStackTrace();
		}
		return layers;
	}

	/**
	 * 获取GeoServer版本号
	 * 
	 * @return
	 */
	public GSVersionDecoder getVersion() {
		GSVersionDecoder version = null;
		if (config == null)
			return version;
		String RESTURL = config.getUrl();
		String RESTUSER = config.getUser();
		String RESTPW = config.getPassword();
		try {
			GeoServerRESTReader reader = new GeoServerRESTReader(RESTURL, RESTUSER, RESTPW);
			version = reader.getGeoserverVersion();
		} catch (Exception mue) {
			mue.printStackTrace();
		}
		return version;
	}
	/////////////////////////////////////////////////

	@Override
	public boolean publish(MapLayer layer) {
		// TODO Auto-generated method stub
		// not finish
		return false;
	}
	
	@Override
	public boolean hasLayer(String layerName) {
		if(StrKit.isBlank(layerName)) return false;
		return serverLayers.containsKey(layerName);
	}

	@Override
	public String getHost() {
		// TODO Auto-generated method stub
		return config.getUrl();
	}

	@Override
	public boolean isCluster() {
		// TODO Auto-generated method stub
		return cluster;
	}

	@Override
	public void addServerLayer(ServerLayer serverLayer) {
		if (serverLayer == null)
			return;
		if (serverLayers == null) {
			serverLayers = Maps.newHashMap();
		}
		serverLayers.put(serverLayer.getName(), serverLayer);
	}
	
	@Override
	public ServerLayer getServerLayer(String layerName) {
		// TODO Auto-generated method stub
		if (serverLayers == null) return null;
		return serverLayers.get(layerName);
	}

	@Override
	public Map<String, ServerLayer> getServerLayers() {
		// TODO Auto-generated method stub
		return serverLayers;
	}
	
	public void setServerLayers(Map<String, ServerLayer> serverLayers) {
		this.serverLayers = serverLayers;
	}

	public void setCluster(boolean cluster) {
		this.cluster = cluster;
	}

	public GeoserverConfig getConfig() {
		return config;
	}

	public void setConfig(GeoserverConfig config) {
		this.config = config;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
/*
	public Map<String, GsWorkspace> getWorkspaces() {
		return workspaces;
	}

	public void setWorkspaces(Map<String, GsWorkspace> workspaces) {
		this.workspaces = workspaces;
	}
*/
	public int getRate() {
		return rate;
	}

	public void setRate(int rate) {
		this.rate = rate;
	}

	public boolean isExist() {
		return exist;
	}

	public void setExist(boolean exist) {
		this.exist = exist;
	}

}
